package cn.lh.basic.service.impl;

import cn.lh.basic.constants.VerifyCodeConstants;
import cn.lh.basic.service.IVerifyService;
import cn.lh.basic.util.MsgSendUtil;
import cn.lh.basic.util.StrUtils;
import cn.lh.basic.util.VerifyCodeUtils;
import cn.lh.org.exception.BusinessException;
import cn.lh.user.domain.User;
import cn.lh.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyServiceImpl implements IVerifyService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    UserMapper userMapper;

    @Override
    public String getImgCode(String key) {
        if (key == null) {
            throw new BusinessException("参数不能为空");
        }
        // 生成长度为4的验证码
        String code = StrUtils.getComplexRandomString(4);
        // 将前端传来的key和验证码存入redis数据库，过期时间为3分钟
        redisTemplate.opsForValue().set(key, code, 3L, TimeUnit.MINUTES);
        // 生成验证码图片(长为100px,宽为40px,内容为code)，并使用Base64将图片编码成字符串
        return VerifyCodeUtils.verifyCode(100, 40, code);
    }

    @Override
    public void sendSmsCode(Map<String, String> map) {
        // 非空验证
        String phone = map.get("phone");
        String imageCode = map.get("imageCode");
        String imageCodeKey = map.get("imageCodeKey");
        if (StringUtils.isEmpty(phone) ||
                StringUtils.isEmpty(imageCode) ||
                StringUtils.isEmpty(imageCodeKey)
        ) {
            throw new BusinessException("参数不能为空");
        }
        User user = userMapper.findByPhone(phone);

        // 判断电话是否已经注册
        if (user != null) {
            throw new BusinessException("该电话号码已注册");
        }
        // 判断图形验证码是否正确 其中imageCodeKey是从localstorage取出发送给服务器的，服务器从redis中取出对应的图片验证码
        Object obj = redisTemplate.opsForValue().get(imageCodeKey);
        if (obj == null) {
            throw new BusinessException("图形验证码已过期");
        }
        String redisImageCodeKey = obj.toString();
        if (!redisImageCodeKey.equalsIgnoreCase(imageCode)) {
            throw new BusinessException("图形验证码输入错误");
        }
        String code = null;
        // 从redis中取出上次发送的验证码信息， 其中键是（业务键+注册电话），值是（上次发送时间戳+上次验证码）
        Object valueObj = redisTemplate.opsForValue().get(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone);
        // 若上次发送的验证码过期或者没有上次则重新生成一个验证码 code
        if (valueObj == null) {
            code = StrUtils.getComplexRandomString(6);
        } else {
            // 若存在上次发送的验证码，则取出上次发送的日期，和验证码信息
            String value = valueObj.toString();
            String redisSmsCode = value.split(":")[1];
            Long timeMillis = Long.parseLong(value.split(":")[0]);
            // 判断距上次发送时间是否小于一分钟 若是抛出异常，不是就继续发送上次验证码给用户
            if (System.currentTimeMillis() - timeMillis < 1 * 60 * 100) {
                throw new BusinessException("系统繁忙");
            } else {
                code = redisSmsCode;
            }
        }
        MsgSendUtil.sendMsg(phone, "你的验证码为:" + code);
        // 重新将短信信息存入redis中短 并设置过期时间未3分钟
        redisTemplate.opsForValue().set(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone, System.currentTimeMillis() + ":" + code, 3, TimeUnit.MINUTES);
    }

    @Override
    public void binderSmsCode(Map<String, String> map) {
        // 非空验证
        String phone = map.get("phone");
        if (phone == null) {
            throw new BusinessException("电话不能为空");
        }
        String code = null;
        // 从redis中取出上次发送的验证码信息， 其中键是（业务键+注册电话），值是（上次发送时间戳+上次验证码）
        Object valueObj = redisTemplate.opsForValue().get(VerifyCodeConstants.BINDER_PREFIX + phone);
        // 若上次发送的验证码过期或者没有上次则重新生成一个验证码 code
        if (valueObj == null) {
            code = StrUtils.getComplexRandomString(6);
        } else {
            // 若存在上次发送的验证码，则取出上次发送的日期，和验证码信息
            String value = valueObj.toString();
            String redisSmsCode = value.split(":")[1];
            Long timeMillis = Long.parseLong(value.split(":")[0]);
            // 判断距上次发送时间是否小于一分钟 若是抛出异常，不是就继续发送上次验证码给用户
            if (System.currentTimeMillis() - timeMillis < 1 * 60 * 100) {
                throw new BusinessException("系统繁忙");
            } else {
                code = redisSmsCode;
            }
        }
        MsgSendUtil.sendMsg(phone, "你的验证码为:" + code);
        // 重新将短信信息存入redis中 并设置过期时间未3分钟
        System.out.println(VerifyCodeConstants.BINDER_PREFIX + phone);
        redisTemplate.opsForValue().set(VerifyCodeConstants.BINDER_PREFIX + phone, System.currentTimeMillis() + ":" + code, 3, TimeUnit.MINUTES);
    }
}
